
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <ctype.h>


typedef struct {
    uint8_t  TID;       // TID_MVB_PD_DATA
    uint8_t  fcode;     // port byte size 端口字节大小 0,1,2,3,4
    uint16_t pdPort;    // port number 端口号
} mvb_data_header;

typedef struct {
    mvb_data_header  header;
    uint8_t  pdData[32];
} mvb_data_full;

#define MVB_DATA_COUNT 1
#define MVB_PD_DATA_LEN 32

#define CONFIG_FILE "config.ini"

// 更健壮地读取配置文件中的key=value，确保每一行都能正确解析
int read_config(const char *filename, char *local_ip, size_t local_ip_len, char *dest_ip, size_t dest_ip_len, uint16_t *dest_port) {
    FILE *fp = fopen(filename, "r");
    if (!fp) return -1;
    char line[256];
    int found_local = 0, found_dest = 0, found_port = 0;
    while (fgets(line, sizeof(line), fp)) {
        // 跳过注释和空行
        char *p = line;
        while (isspace((unsigned char)*p)) p++;
        if (*p == '#' || *p == ';' || *p == '\0' || *p == '\n')
            continue;

        // 查找等号
        char *eq = strchr(p, '=');
        if (!eq) continue;
        *eq = '\0';
        char *key = p;
        char *val = eq + 1;

        // 去除key末尾空白
        char *kend = key + strlen(key) - 1;
        while (kend > key && isspace((unsigned char)*kend)) {
            *kend = '\0';
            kend--;
        }

        // 去除val首尾空白
        while (*val && isspace((unsigned char)*val)) val++;
        char *vend = val + strlen(val) - 1;
        while (vend > val && (isspace((unsigned char)*vend) || *vend == '\n' || *vend == '\r')) {
            *vend = '\0';
            vend--;
        }

        if (strcmp(key, "local_ip") == 0) {
            strncpy(local_ip, val, local_ip_len-1);
            local_ip[local_ip_len-1] = '\0';
            found_local = 1;
        } else if (strcmp(key, "dest_ip") == 0) {
            strncpy(dest_ip, val, dest_ip_len-1);
            dest_ip[dest_ip_len-1] = '\0';
            found_dest = 1;
        } else if (strcmp(key, "dest_port") == 0) {
            *dest_port = (uint16_t)atoi(val);
            found_port = 1;
        }
    }
    fclose(fp);
    // 检查是否都读取到了
    if (!found_local || !found_dest || !found_port) {
        return -2;
    }
    return 0;
}

// 发送UDP数据包并绑定本地IP
int udp_send_packet_bind(const char *ip, uint16_t port, const void *data, size_t data_len, const char *local_ip) {
    if (!ip || !data || data_len == 0 || !local_ip) {
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket");
        return -2;
    }

    // 绑定本地IP
    struct sockaddr_in local_addr;
    memset(&local_addr, 0, sizeof(local_addr));
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = 0; // 让系统自动分配端口
    if (inet_pton(AF_INET, local_ip, &local_addr.sin_addr) != 1) {
        close(sockfd);
        return -3;
    }
    if (bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0) {
        perror("bind");
        close(sockfd);
        return -4;
    }

    // 设置目标地址
    struct sockaddr_in dest_addr;
    memset(&dest_addr, 0, sizeof(dest_addr));
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(port);
    if (inet_pton(AF_INET, ip, &dest_addr.sin_addr) != 1) {
        close(sockfd);
        return -5;
    }

    ssize_t sent = sendto(sockfd, data, data_len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    close(sockfd);

    if (sent != (ssize_t)data_len) {
        return -6;
    }

    return 0;
}

int main() {
    char local_ip[32] = "";
    char dest_ip[32] = "";
    uint16_t dest_port = 0;
    if (read_config(CONFIG_FILE, local_ip, sizeof(local_ip), dest_ip, sizeof(dest_ip), &dest_port) != 0) {
        fprintf(stderr, "Failed to read config file %s\n", CONFIG_FILE);
        return 1;
    }

    printf("local_ip: %s, dest_ip: %s, dest_port: %d\n", local_ip, dest_ip, dest_port);
    // 构建一组 mvb_data_full 数据 
    while(1) {
        // const char *dest_ip = "192.168.0.200";
        // uint16_t dest_port = 8000;
        for (int i = 0; i < MVB_DATA_COUNT; ++i) {
            size_t total_len = sizeof(mvb_data_header) + MVB_PD_DATA_LEN;
            mvb_data_full *data = (mvb_data_full *)malloc(total_len);
            if (!data) {
                fprintf(stderr, "malloc failed\n");
                return 1;
            }

            // 填充 header
            // INSERT_YOUR_CODE
            // 数据采用的是大端模式来存储
            data->header.TID = 0x21; // 单字节，无需转换
            data->header.fcode = 4;  // 单字节，无需转换
            // pdPort为uint16_t，需转为大端
            data->header.pdPort = htons(0x03E8);

            // 填充 pdData
            for (int j = 0; j < MVB_PD_DATA_LEN; ++j) {
                data->pdData[j] = (uint8_t)(i * 10 + j );
            }


            // INSERT_YOUR_CODE
            // 以十六进制输出data内容
            // printf("Packet %d hex dump: ", i);
            for (size_t k = 0; k < total_len; ++k) {
                printf("%02X ", ((uint8_t*)data)[k]);
            }
            printf("\n");

            

            // 优化：在udp_send_packet中增加绑定本地网卡的参数
            // 这里直接传递本地IP作为参数，便于灵活指定
            // const char *local_ip = "192.168.0.76";
            int ret = udp_send_packet_bind(dest_ip, dest_port, data, total_len, local_ip);

            printf("\n%d\n", ret);
            if (ret != 0) {
                fprintf(stderr, "udp_send_packet failed for packet %d\n", i);
            } else {
                printf("Sent data sizeof %d to %s:%d\n", total_len, dest_ip, dest_port);
            }

            free(data);
        }
        
        sleep(2);
    }
    

    return 0;
}
